﻿( function() {
	var $ = function(id) {
		if (typeof id == 'string') {
			return document.getElementById(id);
		}
		return id;
	};
	var monthArray = {
		en : [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ],
		zh_cn : [ '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月' ]
	};
	var dayArray = {
		en : [ 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa' ],
		zh_cn : [ '日', '一', '二', '三', '四', '五', '六' ]
	};

	var DatePicker = function(name) {
		this.name = name;
		this.dateSeparator = '-';
		this.showing = false;
	};

	DatePicker.prototype.show = function() {
		var bindedObject = null;
		var localeString = null;
		if (arguments.length > 0) {
			bindedObject = $(arguments[0]);
		}
		if (arguments.length > 1) {
			localeString = arguments[1];
		}
		var e = getEvent();
		this.bindedObject = bindedObject || e.target || e.srcElement;
		this.localeString = (localeString || 'zh_cn').toLowerCase();
		this.generateHtml();
		this.initDate();
		this.setPosition();
		$(this.name + 'Container').style.display = 'block';
		stopBubble(e);
		this.showing = true;
	};

	DatePicker.prototype.hide = function() {
		if (this.showing) {
			$(this.name + 'Container').style.display = 'none';
			this.showing = false;
		}
	};

	DatePicker.prototype.generateHtml = function() {
		if (this.hasHtml) {
			return;
		}

		var calBody = '<table width="100%" cellspacing="1" cellpadding="0">';
		calBody += '<tr><td colspan="7">';
		calBody += '<table width="100%" cellspacing="0" cellpadding="0"><tr class="datePickerTitle">';
		calBody += '<td class="cellArrow" onclick="' + this.name + '.jumpTo(-12);">&lt;&lt;</td>';
		calBody += '<td class="cellArrow" onclick="' + this.name + '.jumpTo(-1);">&nbsp;&lt;</td>';
		calBody += '<td class="datePickerMonthTD" id="' + this.name + 'MonthTD"></td>';
		calBody += '<td id="' + this.name + 'YearTD"></td>';
		calBody += '<td class="cellArrow" onclick="' + this.name + '.jumpTo(1);">&gt;&nbsp;</td>';
		calBody += '<td class="cellArrow" onclick="' + this.name + '.jumpTo(12);">&gt;&gt;</td>';
		calBody += '</tr></table>';
		calBody += '</td></tr>';
		calBody += '<tr class="datePickerHead">';
		for ( var i = 0; i < 7; i++) {
			calBody += '<td id="' + this.name + 'DayTD' + i + '"></td>';
		}
		calBody += '</tr>';
		for (i = 0; i < 6; i++) {
			calBody += '<tr>';
			for ( var j = 0; j < 7; j++) {
				calBody += '<td id="' + this.name + 'DateTD' + (i * 7 + j) + '"></td>';
			}
			calBody += '</tr>';
		}
		calBody += '</table>';

		// For damn SELECT in IE6
		calBody += '<iframe style="position:absolute;z-index:-1;width:100%;height:expression(this.parentNode.firstChild.offsetHeight);top:0;left:0;scrolling:no;" frameborder="0" src="about:blank"></iframe>';

		var calDiv = document.createElement('div');
		calDiv.id = this.name + 'Container';
		calDiv.className = 'datePickerContainer';
		calDiv.innerHTML = calBody;
		calDiv.onclick = function() {
			stopBubble(getEvent());
		};
		calDiv.onselectstart = calDiv.onmousedown = calDiv.oncontextmenu = function() {
			return false;
		};
		document.body.appendChild(calDiv);
		this.hasHtml = true;
	};

	DatePicker.prototype.initDate = function() {
		var today = new Date();
		this.currentYear = today.getFullYear();
		this.currentMonth = today.getMonth() + 1;
		if (/\d{2,4}\-?\/?\d{1,2}\-?\/?\d{1,2}/.test(this.bindedObject.value)) {
			var tmp = this.bindedObject.value.split(this.dateSeparator);
			if (tmp.length == 3) {
				this.currentYear = this.defaultYear = parseInt(tmp[0], 10);
				this.currentMonth = this.defaultMonth = parseInt(tmp[1], 10);
				this.defaultDate = parseInt(tmp[2], 10);
			}
		}
		this.refresh();
	};
	
	// Called when cell date is clicked
	DatePicker.todo = function() {
		this.datepicker.bindedObject.value = this.title;
		this.datepicker.hide();
	};

	DatePicker.prototype.refresh = function() {
		var days = dayArray[this.localeString];
		for ( var i = 0; i < days.length; i++) {
			$(this.name + 'DayTD' + i).innerHTML = days[i];
		}

		var dateArray = this.getDateArray();
		var today = new Date();
		for (i = 0; i < dateArray.length; i++) {
			var td = $(this.name + 'DateTD' + i);
			td.innerHTML = parseInt(dateArray[i].substr(8, 2), 10);
			td.onmouseover = function() {
				this.className = 'cellOver';
			};
			td.datepicker = this;
			td.onclick = DatePicker.todo;
			td.title = dateArray[i];
			var tmpYear = parseInt(dateArray[i].substr(0, 4), 10);
			var tmpMonth = parseInt(dateArray[i].substr(5, 2), 10);
			var tmpDate = parseInt(dateArray[i].substr(8, 2), 10);
			if (today.getFullYear() == tmpYear && today.getMonth() + 1 == tmpMonth && today.getDate() == tmpDate) {
				td.className = 'cellToday';
				td.onmouseout = function() {
					this.className = 'cellToday';
				};
			} else if (this.defaultYear == tmpYear && this.defaultMonth == tmpMonth && this.defaultDate == tmpDate) {
				td.className = 'cellCurrent';
				td.onmouseout = function() {
					this.className = 'cellCurrent';
				};
			} else if (this.currentYear == tmpYear && this.currentMonth == tmpMonth) {
				td.className = 'cellOut';
				td.onmouseout = function() {
					this.className = 'cellOut';
				};
			} else {
				td.className = 'cellOther';
				td.onmouseout = function() {
					this.className = 'cellOther';
				};
			}
		}
		$(this.name + 'YearTD').innerHTML = this.currentYear;
		$(this.name + 'MonthTD').innerHTML = monthArray[this.localeString][this.currentMonth - 1];
	};

	DatePicker.prototype.getDateArray = function() {
		var dateArray = [];
		var lastDay = new Date(this.currentYear, this.currentMonth, 0).getDate();
		var dayOfWeek = new Date(this.currentYear, this.currentMonth - 1, 1).getDay();
		var tmpMonth = this.currentMonth - 1;
		var tmpYear = this.currentYear;
		if (dayOfWeek === 0) {
			dayOfWeek = 7;
		}
		if (tmpMonth === 0) {
			tmpMonth = 12;
			tmpYear--;
		}
		var tmpLastDay = new Date(tmpYear, tmpMonth, 0).getDate();
		for ( var i = dayOfWeek - 1; i >= 0; i--) {
			dateArray[i] = this.formatDate(tmpYear, tmpMonth, tmpLastDay--);
		}

		for (i = 0; i < lastDay; i++) {
			dateArray[dayOfWeek + i] = this.formatDate(this.currentYear, this.currentMonth, i + 1);
		}

		tmpMonth = this.currentMonth + 1;
		tmpYear = this.currentYear;
		if (tmpMonth == 13) {
			tmpMonth = 1;
			tmpYear++;
		}
		for (i = 0; i < 42 - lastDay - dayOfWeek; i++) {
			dateArray[lastDay + dayOfWeek + i] = this.formatDate(tmpYear, tmpMonth, i + 1);
		}
		return dateArray;
	};

	DatePicker.prototype.setPosition = function() {
		function getPosition(object) {
			var x = object.offsetLeft;
			var y = object.offsetTop;
			while (object && object.offsetParent) {
				x += object.offsetParent.offsetLeft;
				y += object.offsetParent.offsetTop;
				object = object.offsetParent;
			}
			return {
				x :x,
				y :y
			};
		}
		var xy = getPosition(this.bindedObject);
		$(this.name + 'Container').style.left = xy.x + 'px';
		$(this.name + 'Container').style.top = xy.y + this.bindedObject.offsetHeight + 2 + 'px';
	};

	DatePicker.prototype.formatDate = function(year, month, date) {
		if (month < 10) {
			month = '0' + month;
		}
		if (date < 10) {
			date = '0' + date;
		}
		return year + this.dateSeparator + month + this.dateSeparator + date;
	};

	DatePicker.prototype.jumpTo = function(months) {
		var tmpMonth = this.currentMonth + months;
		this.currentYear += Math.floor((tmpMonth - 1) / 12);
		this.currentMonth = (tmpMonth % 12 + 11) % 12 + 1;
		this.refresh();
	};
	
	document.write('<style type=\'text/css\'>');
	document.write('.datePickerContainer {position: absolute; padding: 4px; background-color: #FFF; border: 1px solid #7B9EBD; display: none; cursor: default; z-index: 99; width: 155px;}');
	document.write('.datePickerContainer .datePickerHead td,.datePickerContainer .datePickerTitle td { color: #FFE; background-color: #003366; height: 20px; }');
	document.write('.datePickerContainer .datePickerMonthTD { width: 60px; }');
	document.write('.datePickerContainer td { text-align: center; font-family: Arial; font-size: 12px; height: 18px; }');
	document.write('.datePickerContainer .cellArrow { cursor: pointer; }');
	document.write('.datePickerContainer .cellOver { background-color: #003366; color: #FF8; border: 1px solid #0000A0; }');
	document.write('.datePickerContainer .cellOut { background-color: #FAFAFA; border: 1px solid #9C9C9C; }');
	document.write('.datePickerContainer .cellCurrent { background-color: #C0C0DD; border: 1px solid #0000A0; }');
	document.write('.datePickerContainer .cellToday { border: 1px solid #FF0000; }');
	document.write('.datePickerContainer .cellOther { background-color: #EEE; color: #808080; border: 1px solid #9C9C9C; }');
	document.write('</style>');

	var getEvent = function() {
		if (window.event) {
			return window.event;
		}
		var func = getEvent.caller;
		while (func !== null) {
			var arg0 = func.arguments[0];
			if (arg0 && (arg0.constructor == Event || arg0.constructor == MouseEvent)) {
				return arg0;
			}
			func = func.caller;
		}
		return null;
	};

	var stopBubble = function(e) {
		if (e && e.stopPropagation) {
			e.stopPropagation();
		} else {
			window.event.cancelBubble = true;
		}
	};

	var domReady = function(fn) {
		if (domReady.done) {
			return fn();
		}

		if (domReady.timer) {
			domReady.ready.push(fn);
		} else {
			addEvent(window, 'load', isDOMReady);
			domReady.ready = [ fn ];

			domReady.timer = setInterval(isDOMReady, 13);
		}
	};

	var isDOMReady = function() {
		if (domReady.done) {
			return false;
		}

		if (document && document.getElementsByTagName && $ && document.body) {
			clearInterval(domReady.timer);
			domReady.timer = null;

			for ( var i = 0; i < domReady.ready.length; i++) {
				domReady.ready[i]();
			}

			domReady.ready = null;
			domReady.done = true;
		}
	};

	var addEvent = function(element, type, fn) {
		if (element.addEventListener) {
			element.addEventListener(type, fn, false);
		} else if (element.attachEvent) {
			element['e' + type + fn] = fn;
			element[type + fn] = function() {
				element['e' + type + fn](window.event);
			};
			element.attachEvent('on' + type, element[type + fn]);
		}
	};

	domReady( function() {
		var datepicker = window.datepicker = new DatePicker('datepicker');
		addEvent(document, 'click', function() {
			datepicker.hide();
		});
	});
})();